//
//  VideoPlayerViewController.m
//  OpenYourEyes
//
//  Created by 沈振烨 on 15/8/14.
//  Copyright (c) 2015年 zhanglei. All rights reserved.
//

#import "VideoPlayerViewController.h"
#import "MoviePlayerView.h"
#import <AVFoundation/AVFoundation.h>
#import "FMDB.h"
#import "AFNetworking.h"


@interface VideoPlayerViewController ()

//  自定义播放界面
@property (nonatomic, strong) MoviePlayerView *moviePlayerView;  //  自定义播放界面
@property (nonatomic, strong) AVPlayer *player;
@property (nonatomic, assign) BOOL isFirstTap;  //  判断是否第一次点击
@property (nonatomic, assign) BOOL isPlayOrParse;  //  判断播放是开始还是停止
@property (nonatomic, strong)FMDatabase *db; //  数据库表
@property (nonatomic, strong) NSTimer *paintingTimer;  //  添加NSTimer
@property (nonatomic, assign) BOOL isCollect;

//  下面三个属性是 缓存电影用的
@property (nonatomic, strong) NSURLRequest * request;
@property (nonatomic, assign) float progress;
@property (nonatomic, strong) AFHTTPRequestOperation  * operation;

//  保存该视频资源的总时长，快进或快退的时候要用
@property (nonatomic, assign) CGFloat totalMovieDuration;

@end

@implementation VideoPlayerViewController

- (void)dealloc
{
    //  移除观察者,使用观察者模式的时候，记得在不使用的时候，进行移除
    [self removeObserverFromPlayerItem:self.player.currentItem];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
    NSLog(@"被释放掉");
}

- (void)loadView
{
    //  创建需要显示的视图
    self.moviePlayerView = [[MoviePlayerView alloc] initWithFrame:[UIScreen mainScreen].bounds];
    self.view = _moviePlayerView;
    self.view.backgroundColor = [UIColor blackColor];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [self createPlayer];
    [self dismissAllViews];
    //  查询数据库,判断是否收藏
    [self isCollection];
    [self isDownload];
}



- (void)createPlayer
{
    //  注册观察者用来观察，是否播放完毕
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(moviePlayDidEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
    //   创建视频播放器层
    //  大家应该看到了appDelgate.m中的注释了，AVPlayer要显示必须创建一个播放器层AVPlayerLayer用于展示，播放器层继承于CALayer，有了AVPlayerLayer之添加到控制器视图的layer中即可
    
    //  创建显示层
    AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
    //  设置frame
    CGRect frame = self.view.bounds;
    frame.size.height = self.view.bounds.size.width;
    frame.size.width = self.view.bounds.size.height;
    playerLayer.frame = frame;
    //  这是视屏的填充模式,默认为AVLayerVideoGravityResizeAspect
    playerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
    //  插入到view的层上面，我没有用addSublayer，因为我想让播放的视图在最下层
    [self.view.layer insertSublayer:playerLayer atIndex:0];
    
    //  给播放界面赋值的标题
    self.moviePlayerView.titleLabel.text = _model.title;
    //  给返回键添加图片
    
    
    //  播放界面返回添加点击事件
    [self.moviePlayerView.returnButton addTarget:self action:@selector(stopMoviePlayToBack:) forControlEvents:UIControlEventTouchUpInside];
    
    //  播放界面添加轻拍手势
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissAllViews:)];
    [self.view addGestureRecognizer:tap];
    
    
    // 屏幕中心播放按钮添加点击事件
    [self.moviePlayerView.playButton addTarget:self action:@selector(playButtonAction:) forControlEvents:UIControlEventTouchUpInside];
    
    
    //  播放进度滑竿添加滑动时间
    [self.moviePlayerView.movieSlider addTarget:self action:@selector(movieSliderValueChanged:) forControlEvents:UIControlEventValueChanged];
    
    //  给音量的滑杆设置事件
    [self.moviePlayerView.voiceSlider addTarget:self action:@selector(voiceSliderValueChanged:) forControlEvents:UIControlEventValueChanged];
    
    //  给增大音量按钮添加点击事件
    [self.moviePlayerView.addVoiceButton addTarget:self action:@selector(doTapAddVoiceValue:) forControlEvents:UIControlEventTouchUpInside];
    
    //  给减小音量按钮添加点击时间
    [self.moviePlayerView.reduceVoiceButton addTarget:self action:@selector(doTapReduceVoiceValue:) forControlEvents:UIControlEventTouchUpInside];
    
    // 给缓存下载添加点击事件
    [self.moviePlayerView.downloadButton addTarget:self action:@selector(download:) forControlEvents:UIControlEventTouchUpInside];
    
    //  给收藏添加点击事件
    [self.moviePlayerView.collectionButton addTarget:self action:@selector(doTapToCollection:) forControlEvents:UIControlEventTouchUpInside];
    
}

//avplayer的懒加载
- (AVPlayer *)player
{
    if (!_player) {
        if (self.url) {

//            NSURL *url = [NSURL URLWithString:_model.playUrl];
            AVPlayerItem *playItem = [AVPlayerItem playerItemWithURL:_url];
            self.player = [AVPlayer playerWithPlayerItem:playItem];
            //  添加进度观察
            [self addProgressObserver];
            [self addObserverToPlayerItem:playItem];
            
        }
    }
    return _player;
}





- (void)stopMoviePlayToBack:(UIButton *)sender
{
    [self dismissViewControllerAnimated:YES completion:nil];
}

- (void)moviePlayDidEnd:(NSNotification *)notif
{
    //  播放按钮设置成播放图片
//    [self.moviePlayerView.playButton setBackgroundImage:[UIImage imageNamed:@"bofang-1"] forState:UIControlStateNormal];
    //  延迟调用方法
    [self performSelector:@selector(backDetailView) withObject:nil afterDelay:1.5];
}

//回详情页
- (void)backDetailView
{
    [self dismissViewControllerAnimated:YES completion:nil];
}

// 点击播放或者暂停 (调用rate 有可能导致无法释放掉)
- (void)playButtonAction:(UIButton *)sender
{
    //  rate 是player的一个属性,判断是暂停还是播放
    if(self.player.rate == 0)
    { //暂停状态
        [sender setImage:[UIImage imageNamed:@"zanting"] forState:UIControlStateNormal];
        [self.player play];
    }else if(self.player.rate == 1)
    {//正在播放
        [self.player pause];
        [sender setImage:[UIImage imageNamed:@"bofang-1"] forState:UIControlStateNormal];
    }
}

- (void)movieSliderValueChanged:(UISlider *)sender
{
    //  先暂停
    [self.player pause];
    //  图片切换
    [_moviePlayerView.playButton setImage:[UIImage imageNamed:@"bofang-1"] forState:UIControlStateNormal];
    
    float current = (float)(self.totalMovieDuration * sender.value);
    CMTime currentTime = CMTimeMake(current, 1);
    //  给avplayer设置进度
    [self.player seekToTime:currentTime completionHandler:^(BOOL finished) {
        [_moviePlayerView.playButton setImage:[UIImage imageNamed:@"zanting"] forState:UIControlStateNormal];
        [self.player play];
    }];

}

//  滑动滑轮改变声音的大小
- (void)voiceSliderValueChanged:(UISlider *)sender
{
    [_player setVolume:sender.value];
}

//  增大音量
- (void)doTapAddVoiceValue:(UIButton *)sender
{
    CGFloat a = _moviePlayerView.voiceSlider.value;
    a = a + 0.1;
    if (a >= 1) {
        a = 1;
    }
    _moviePlayerView.voiceSlider.value = a;
    [_player setVolume:a];
}

//  减小音量
- (void)doTapReduceVoiceValue:(UIButton *)sender
{
    CGFloat a = _moviePlayerView.voiceSlider.value;
    a = a - 0.1;
    if (a <= 0) {
        a = 0;
    }
    _moviePlayerView.voiceSlider.value = a;
    [_player setVolume:a];
}

//  第一次进入子视图是消失状态
- (void)dismissAllViews
{
    _moviePlayerView.topView.frame = CGRectMake(0, -55, self.view.bounds.size.width, 55);
    _moviePlayerView.bottomView.frame = CGRectMake(0, self.view.bounds.size.height, self.view.bounds.size.width, 50);
    _moviePlayerView.centerView.alpha = 0;
}


//  手势的点击事件,子视图消失或者出现
- (void)dismissAllViews:(UITapGestureRecognizer *)tap
{
    //  防止循环引用
    __weak typeof(self) myself = self;
    if (!self.isFirstTap)
    {
        [UIView animateWithDuration:0.2 animations:^{
            
            myself.moviePlayerView.topView.frame = CGRectMake(0, 0, myself.view.bounds.size.width, 55);
            myself.moviePlayerView.bottomView.frame = CGRectMake(0, myself.view.bounds.size.height - 50, myself.view.bounds.size.width, 50);
            myself.moviePlayerView.centerView.alpha = 0.6;
            
            myself.isFirstTap = YES;
            
        }];
    } else
    {
        
        [UIView animateWithDuration:0.2 animations:^{
            myself.moviePlayerView.topView.frame = CGRectMake(0, -55, myself.view.bounds.size.width, 55);
            myself.moviePlayerView.bottomView.frame = CGRectMake(0, myself.view.bounds.size.height, myself.view.bounds.size.width, 50);
            myself.moviePlayerView.centerView.alpha = 0;
            
            myself.isFirstTap = NO;
        }];
        
    }
    
   
}




// 点击收藏,收藏本视频 将本视频的相关信息写入数据库中
- (void)doTapToCollection:(UIButton *)sender
{
    
    NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:@"Collection.db"];
    NSLog(@"%@",path);
    _db = [FMDatabase databaseWithPath:path];
    if (![_db open]) {
        NSLog(@"数据库打开失败");
        return;
    }
    [_db executeUpdate:@"CREATE TABLE IF NOT EXISTS Collection (Category text, CoverBlurred text, CoverForDetail text, CoverForFeed text, CoverForSharing text, Date integer, Description text, Duration integer, ID integer,Idx integer, PlayUrl text, RawWebUrl text, Title text, WebUrl text)"];
    
    if (_isCollect == YES)
    {
        [self deleteModelFromDatabase];
        [_moviePlayerView.collectionButton setImage:[UIImage imageNamed:@"iconfont-weishoucang"] forState:UIControlStateNormal];
        _isCollect = NO;
        
    } else
    {
        [self makeModelToDatabase];
        [_moviePlayerView.collectionButton setImage:[UIImage imageNamed:@"yishoucang"] forState:UIControlStateNormal];
        _isCollect = YES;
    }

    
}

#pragma park - 将model存储到数据库中
- (void)makeModelToDatabase
{
    NSNumber *duration = [NSNumber numberWithInteger:_model.duration];
    NSNumber *ID = [NSNumber numberWithInteger:_model.ID];
    NSNumber *idx = [NSNumber numberWithInteger:_model.idx];
    NSNumber *date = [NSNumber numberWithInteger:_model.date];
    
    [_db executeUpdate:@"INSERT INTO Collection (Category, CoverBlurred,CoverForDetail,CoverForFeed,CoverForSharing,Date,Description,Duration,ID,Idx,PlayUrl,RawWebUrl,Title,WebUrl) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)",_model.category,_model.coverBlurred,_model.coverForDetail,_model.coverForFeed,_model.coverForSharing,date,_model.Description,duration,ID,idx,_model.playUrl,_model.rawWebUrl,_model.title,_model.webUrl];
}

#pragma park - 将model从数据库删除
- (void)deleteModelFromDatabase
{
//    //  删除所有
//    [_db executeUpdate:@"DELETE FROM Collection"];
//    NSLog(@"删除所有");
    
    //  按title 查询删除
    NSString *str = _model.title;
    //  删除数据库的方法
    NSString *deleteStr = [NSString stringWithFormat:@"DELETE fROM %@ where %@ = '%@'",@"Collection",@"Title",str];
    [_db executeUpdate:deleteStr];
    
}


// 点击缓存,将视频缓存到本地
- (void)download:(UIButton *)sender
{
    NSLog(@"调用详情页的按钮点击事件");
    //  使用代理的方法 可以实现
    [_delegate doTapTotalScrollViewDownloadButton];
        
    //  练习使用block方法 可以实现
    _moviePlayerView.downloadButton.userInteractionEnabled = NO;
    _moviePlayerView.downloadButton.alpha = 0.4;
    if (self.myblock != nil) {
        self.myblock();
    }
    
}


#pragma park - 封装数据库查询,目的将我的收藏持久
- (void)isCollection
{
    NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:@"Collection.db"];
    NSLog(@"%@",path);
    _db = [FMDatabase databaseWithPath:path];
    if (![_db open]) {
        NSLog(@"数据库打开失败");
        return;
    }

    //  查询数据库
    FMResultSet *rs = [_db executeQuery:@"SELECT * FROM Collection where title = ?",_model.title];
    while ([rs next])  //  类库中的方法  循环查询
    {
        [_moviePlayerView.collectionButton setImage:[UIImage imageNamed:@"yishoucang"] forState:UIControlStateNormal];
        _isCollect = YES;
        return;
    }
    _isCollect = NO;
}

#pragma park - 封装判断是否下载到本地
- (void)isDownload
{
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSLog(@"%@",_model.title);
    if ([fileManager fileExistsAtPath:[self IsExistdownLoadFilePath]] | [fileManager fileExistsAtPath:[self IsExistFilePath]])
    {
        _moviePlayerView.downloadButton.userInteractionEnabled = NO;
        _moviePlayerView.downloadButton.alpha = 0.4;
    } else
    {
        _moviePlayerView.downloadButton.userInteractionEnabled = YES;
        _moviePlayerView.downloadButton.alpha = 1.0;

    }
}


//  下载路径
- (NSString *)IsExistFilePath
{
    NSString * cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)firstObject];
    
    NSString * filePath = [cachePath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.mp4",_model.title]];
    return filePath;
}

//下载完成的路径
- (NSString *)IsExistdownLoadFilePath
{
    NSFileManager * fileManager = [NSFileManager defaultManager];
    
    NSString * tmp = [NSHomeDirectory() stringByAppendingString:@"/tmp"];
    
    NSString * videoPath = [tmp stringByAppendingString:@"/_model"];
    if (![fileManager fileExistsAtPath:videoPath]) {
        [fileManager createDirectoryAtPath:videoPath withIntermediateDirectories:YES attributes:nil error:nil];
    }
    NSString * downLoadFinished = [videoPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.mp4",self.model.title]];
    return downLoadFinished;
    
}
//计算缓存路径的大小
- (unsigned long long)fileSizeAtPath:(NSString *)fileAbsolutePath
{
    signed long long fileSize = 0;
    NSFileManager * fileManager = [NSFileManager new];
    if ([fileManager fileExistsAtPath:fileAbsolutePath]) {
        NSError *error = nil;
        NSDictionary *fileDict = [fileManager attributesOfItemAtPath:fileAbsolutePath error:&error];
        if (!error && fileDict) {
            fileSize = [fileDict fileSize];
        }
    }
    return fileSize;
}




//  依靠AVPlayer的- (id)addPeriodicTimeObserverForInterval:(CMTime)interval queue:(dispatch_queue_t)queue usingBlock:(void (^)(CMTime time))block方法获得播放进度，这个方法会在设定的时间间隔内定时更新播放进度，通过time参数通知客户端。相信有了这些视频信息播放进度就不成问题了，事实上通过这些信息就算是平时看到的其他播放器的缓冲进度显示以及拖动播放的功能也可以顺利的实现。
- (void)addProgressObserver{
    //  获取当前媒体资源管理对象
    AVPlayerItem *playerItem = self.player.currentItem;
    
    __weak typeof(self) mySelf = self;
    //  设置每秒执行一次
    [self.player addPeriodicTimeObserverForInterval:CMTimeMake(1.0, 1.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
        //  获取当前的进度
        float current = CMTimeGetSeconds(time);
        //  获取全部资源的大小
        float total = CMTimeGetSeconds([playerItem duration]);
        //  计算出进度
        if (current) {
            [mySelf.moviePlayerView.movieSlider setValue:(current / total) animated:YES];
            
            NSDate *d = [NSDate dateWithTimeIntervalSince1970:current];
            
            NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
            if (current/3600 >=1) {
                [formatter setDateFormat:@"mm:ss"];
            }else{
                [formatter setDateFormat:@"mm:ss"];
            }
            NSString * showTimeNew = [formatter stringFromDate:d];
            
            mySelf.moviePlayerView.currentTimeLabel.adjustsFontSizeToFitWidth = YES;
            
            mySelf.moviePlayerView.currentTimeLabel.text = showTimeNew;
            
            
            
        }
    }];
    
}

//  这个方法，用来取得播放进度，播放进度就没有其他播放器那么简单了。在系统播放器中通常是使用通知来获得播放器的状态，媒体加载状态等，但是无论是AVPlayer还是AVPlayerItem（AVPlayer有一个属性currentItem是AVPlayerItem类型，表示当前播放的视频对象）都无法获得这些信息。当然AVPlayerItem是有通知的，但是对于获得播放状态和加载状态有用的通知只有一个：播放完成通知AVPlayerItemDidPlayToEndTimeNotification。在播放视频时，特别是播放网络视频往往需要知道视频加载情况、缓冲情况、播放情况，这些信息可以通过KVO监控AVPlayerItem的status、loadedTimeRanges属性来获得当AVPlayerItem的status属性为AVPlayerStatusReadyToPlay是说明正在播放，只有处于这个状态时才能获得视频时长等信息；当loadedTimeRanges的改变时（每缓冲一部分数据就会更新此属性）可以获得本次缓冲加载的视频范围（包含起始时间、本次加载时长），这样一来就可以实时获得缓冲情况。

-(void)addObserverToPlayerItem:(AVPlayerItem *)playerItem{
    //监控状态属性，注意AVPlayer也有一个status属性，通过监控它的status也可以获得播放状态
    [playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
    //监控网络加载情况属性
    [playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];
}
-(void)removeObserverFromPlayerItem:(AVPlayerItem *)playerItem{
    [playerItem removeObserver:self forKeyPath:@"status"];
    [playerItem removeObserver:self forKeyPath:@"loadedTimeRanges"];
}


//  观察者的方法，会在加载好后触发，我们可以在这个方法中，保存总文件的大小，用于后面的进度的实现
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    AVPlayerItem *playerItem=object;
    if ([keyPath isEqualToString:@"status"]) {
        AVPlayerStatus status= [[change objectForKey:@"new"] intValue];
        if(status==AVPlayerStatusReadyToPlay){
//            NSLog(@"正在播放...，视频总长度:%.2f",CMTimeGetSeconds(playerItem.duration));
            
            CMTime totalTime = playerItem.duration;
            //因为slider的值是小数，要转成float，当前时间和总时间相除才能得到小数,因为5/10=0
            self.totalMovieDuration = (CGFloat)totalTime.value/totalTime.timescale;
            
            NSDate *d = [NSDate dateWithTimeIntervalSince1970:_totalMovieDuration];
            
            
            NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
            if (_totalMovieDuration/3600 >=1) {
                [formatter setDateFormat:@"mm:ss"];
            }else{
                [formatter setDateFormat:@"mm:ss"];
            }
            NSString * showTimeNew = [formatter stringFromDate:d];
            self.moviePlayerView.totalTimeLabel.adjustsFontSizeToFitWidth = YES;
            self.moviePlayerView.totalTimeLabel.text = showTimeNew;
        }
    }else if([keyPath isEqualToString:@"loadedTimeRanges"]){
        NSArray *array=playerItem.loadedTimeRanges;
        CMTimeRange timeRange = [array.firstObject CMTimeRangeValue];//本次缓冲时间范围
        float startSeconds = CMTimeGetSeconds(timeRange.start);
        float durationSeconds = CMTimeGetSeconds(timeRange.duration);
        NSTimeInterval totalBuffer = startSeconds + durationSeconds;//缓冲总长度
        _moviePlayerView.progressView.progress = totalBuffer / _totalMovieDuration;
        _moviePlayerView.progressView.progressTintColor = [UIColor whiteColor];
//        NSLog(@"共缓冲：%.2f",totalBuffer);
        
    }
}

//  进入该视图控制器自动横屏进行播放
- (BOOL)shouldAutorotate
{
    [self.player play];
    [_moviePlayerView.playButton setImage:[UIImage imageNamed:@"zanting"] forState:UIControlStateNormal];
    return NO;
}

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskLandscape;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return UIInterfaceOrientationLandscapeLeft ;
}




- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end
